package com.cskaoyan.javase.recursion._0introduction;

/**
 * 递归的引入
 *
 * 我们已经学习过方法，使用过方法了。
 * 方法体中是可以调用方法的，那么如果在方法体中调用方法自身呢？
 *
 * 特别的，
 * 在一个方法当中再次调用这个方法，就像故事里提到同样的故事一样
 * 我们把方法在运行时调用自身的情况，称之为递归，又叫做递归调用。
 *
 * 怎么使用递归?
 *      1.要想使用递归,首先必不可少的就是递归体
 *        递归体: 指的是方法体当中,自身调用自身的语句
 *        递归体对于递归而言,必不可少.
 *
 *      2.如果一个递归,只存在递归体,就会导致方法栈帧只进不出,一定会栈溢出
 *        所以一个正常执行的递归,需要一个终止递归的条件,称之为"递归的出口"
 *        一个正常执行的递归,必须要有"递归的出口"
 *
 *
 *      3.一个递归有递归体,有递归的出口,那么这个递归就是安全的吗?
 *          不是绝对安全的
 *          还需要考虑递归的次数(递归的深度)
 *          不能超过栈内存的大小
 *          一旦递归的深度超过栈内存的大小,照样会栈溢出
 *
 * 递归是很危险的,没有绝对安全的递归的
 * 只要用递归,就要考虑风险
 *
 * @since 17:02
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*
            分析一下这个递归:
              sum(10) = 10 + sum(9);
              sum(9) = 9 + sum(8);
              sum(8) = 8 + sum(7);
              ....
            以上过程不能自己停下来,那么程序的执行结果是:
                1.死循环
                2.运行出错,程序报错终止
                3.电脑受不了,它自己炸了(这个肯定不会)

             运行程序发现程序报错,抛出异常,终止执行了
             抛出的异常叫: StackOverflowError(栈溢出错误)
             Error是错误,它是一种比Exception更加严重的异常(错误)

             为什么会StackOverflowError呢?栈溢出?是什么栈溢出呢?
             JVM栈溢出了
             这个递归过程中,为什么会导致JVM栈溢出呢?
             因为这个递归调用的过程中,方法栈帧只进不出,而JVM栈内存空间有限
             最终一定会栈溢出,导致程序崩溃报错,终止.

             idea警告:
             Method 'sum()' recurses infinitely, and can only end by throwing an exception
         */
        // System.out.println(sum(10));

        // 有递归出口后,调用sum方法
        System.out.println(sum(100));

        // 递归的深度超出JVM栈大小
        System.out.println(sum(15000));
    }

    public static long sum(int num) {
        // 递归的出口
        if (num == 0) {
            return 0;
        }
        return num + sum(num - 1);
    }

}
